package touchtrack.view.graph;

import org.mt4j.MTApplication;
import org.mt4j.components.MTComponent;

import processing.core.PApplet;
import touchtrack.Settings;
import touchtrack.exception.ItemNotFoundException;
import traer.physics.Particle;
import traer.physics.Spring;

/**
 * Represents a spring (an edge) between two track nodes.
 * 
 * @author	MuMe09 team 6
 * 			http://mumetech.wordpress.com/
 */
public class TrackSpring extends MTComponent
{
	private MTApplication app;
	
	/**
	 * Spring constructor.
	 * 
	 * @param	MTApplication app
	 * @param 	TrackNode track1
	 * @param 	TrackNode track2
	 */
	public TrackSpring(MTApplication app, TrackNode track1, TrackNode track2)
	{
		super(app);
		this.app = app;
		
		this.track1 = track1;     
	    this.track2 = track2;
	}
	
	/***************************************************************************
	 * 								Drawing
	 ***************************************************************************/
	
	/**
	 * Draws the spring as a line.
	 */
	public void draw(TrackGraph graph)
	{
		//app.line(track1.getCenterX(), track1.getCenterY(), track2.getCenterX(), track2.getCenterY());
		
		if (graph != null && spring != null)
		{
	        Particle a = spring.getOneEnd();
	        Particle b = spring.getTheOtherEnd();
	        
	        if (a != null && b != null)
	        {
	            app.smooth();
	            app.strokeWeight(4);
	            app.strokeCap(PApplet.ROUND);
	            app.stroke(Settings.SPRING_COLOR);
		        
		        int xa = (int) (PApplet.map(a.position().x(), graph.getMinX(), graph.getMaxX(), graph.BORDER, app.getWidth() - graph.BORDER));
		        int ya = (int) (PApplet.map(a.position().y(), graph.getMinY(), graph.getMaxY(), graph.BORDER, app.getHeight() - graph.BORDER));
		        int xb = (int) (PApplet.map(b.position().x(), graph.getMinX(), graph.getMaxX(), graph.BORDER, app.getWidth() - graph.BORDER));
		        int yb = (int) (PApplet.map(b.position().y(), graph.getMinY(), graph.getMaxY(), graph.BORDER, app.getHeight() - graph.BORDER));
		        
		        app.line(xa, ya, xb, yb);
	        }
		}
	}
	
	/***************************************************************************
	 * 								Nodes
	 ***************************************************************************/
	
	/**
	 * Checks whether the spring is between the two given track nodes.
	 * 
	 * @param 	TrackNode track1
	 * @param 	TrackNode track2
	 * @return	boolean
	 */
	public boolean between(TrackNode track1, TrackNode track2)
	{
		return ( this.track1.equals(track1) && this.track2.equals(track2) ) 
			|| ( this.track1.equals(track2) && this.track2.equals(track1) );
	}
	
	/**
	 * Given a node, this method returns the other node.
	 * 
	 * @param 	TrackNode track
	 * @return	TrackNode
	 * @throws 	ItemNotFoundException 
	 */
	public TrackNode getOtherNode(TrackNode track) 
		throws ItemNotFoundException
	{
		if (this.track1.equals(track))
			return track2;
		else if (this.track2.equals(track))
			return track1;
		else
			throw new ItemNotFoundException("Node not found: " + track);
	}
	
	public TrackNode track1;
	public TrackNode track2;
	
	/***************************************************************************
	 * 								Spring properties
	 ***************************************************************************/
	
	/**
	 * Returns the strength of the spring.
	 * 
	 * @return	float strength
	 */
	public float getStrength()
	{
		return this.track1.getTrackInterface().getSimilarity(this.track2.getTrackInterface());
	}
	  
	/**
	 * @return	length
	 */
	public float getLength()
	{
		return track1.getDistance(track2);
	}
	  
	/**
	 * @return	length over x
	 */
	public float getLengthX()
	{
		return track1.getDistanceX(track2);
	}
	  
	/**
	 * @return	length over y
	 */
	public float getLengthY()
	{
		return track1.getDistanceY(track2);
	}
	
	public Spring spring;

	/***************************************************************************
	 * 								Java stuff
	 ***************************************************************************/
	
	/**
	 * @param	Object
	 * @return	boolean
	 */
	public boolean equals(Object obj)
	{
		if (obj instanceof TrackSpring)
		{
			TrackSpring s = (TrackSpring) obj;
			return this.between(s.track1, s.track2);
		}
		else
		{
			return false;
		}
	}
	
	/**
	 * @return	String
	 */
	public String toString()
	{
		return "From \"" + track1 + "\" to \"" + track2 + "\"";
	}
}